
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.game.TiledLayer;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;

public class PlayGame extends GameCanvas implements Runnable, CommandListener {

    private int nNgang = 8;
    private int nDoc = 10;
    private int iScore;
    private int DelayVeDuongDi = 600;
    public static int delay = 200;
    private static int timeMax = 5;
    private Main iMain;
    private Command cmdExit;
    private Command cmdPause;
    private LayerManager iLayerManager;
    private Image imgQuit;
    private Image imgPause;
    private Image imgWin;
    private Image imgOver;
    private boolean iIsActive;
    private TiledLayer iBgLayer;
    private GameDesign gameDesign;
    private Sprite[][] anh;
    private int[] xLuu;
    private int[] yLuu;
    private int x;
    private int y;
    private int xChon;
    private int yChon;
    private boolean daChon = false;
    private int time = timeMax * 1000 / delay;
    private boolean isPause = false;
    private boolean isExit = false;
    private boolean isOver = false;
    private boolean isWin = false;
    private MenuScreen iMenuScreen;
    private Graphics g;
    private AddScore iAddScore;
    //
    // SO luong cac' ca.p anh giong nhau
    private int nCap = 2;
    private int[][] iGiongNhauX;    // Vi tri cac' anh giong' nhau
    private int[][] iGiongNhauY;    // Thu tu cac' anh giong nhau
    private int[][] maTranDuongDi;  //
    // Ma tran duong` di dang
    /* 1 1 1 1 1 1
     * 1 x x x x 1
     * 1 x x x x 1
     * 1 1 1 1 1 1      
     */
    private Point[] path;
    // Chua thong tin duong` di dung'
    private int nPath;  // So luong phan tu
    private boolean andiem;
    private int demve = -1;
    private Player moveSound;
    private Player wrongSound;
    private Player pauseSound;
    private Player exitSound;
    private Player overSound;
    private Player winSound;
    private int[][] mtNoMove;

    public static int getTimeMax() {
        return timeMax;
    }

    public PlayGame(Main aMain, MenuScreen aMenuScreen) {
        super(true);
        setFullScreenMode(true);
        iMain = aMain;
        iMenuScreen = aMenuScreen;

        try {
            imgQuit = Image.createImage("pause.png");
            imgPause = Image.createImage("pause.png");
            imgOver = Image.createImage("over.png");
            imgWin = Image.createImage("win.png");
        } catch (Exception e) {
        };

        cmdExit = new Command("Quit", Command.EXIT, 0);
        this.addCommand(cmdExit);
        cmdPause = new Command("Pause", Command.BACK, 0);
        this.addCommand(cmdPause);
        setCommandListener(this);
    }

    public void Start() {
        g = getGraphics();
        iScore = 0;
        x = 40;
        y = 50;

        ///////////
        path = new Point[(nNgang + 2) * (nDoc + 2)];
        nPath = 0;
        iGiongNhauX = new int[nNgang][nDoc];
        iGiongNhauY = new int[nNgang][nDoc];
        maTranDuongDi = new int[nNgang + 2][nDoc + 2];
        for (int i = 0; i < nNgang + 2; ++i) {
            for (int j = 0; j < nDoc + 2; ++j) {
                if ((i != 0) && (j != 0) && (i != (nNgang + 1)) && (j != (nDoc + 1))) {
                    maTranDuongDi[i][j] = 0;
                } else {
                    maTranDuongDi[i][j] = 1;
                }
            }
        }
        mtNoMove = new int[nNgang][nDoc];
        for (int i = 0; i < nNgang; ++i) {
            for (int j = 0; j < nDoc; ++j) {
                mtNoMove[i][j] = 1;
            }
        }
        /* 1 1 1 1 1 1
         * 1 0 0 0 0 1  --> 0 la` co' anh, ko di qua duoc
         * 1 0 0 0 0 1
         * 1 1 1 1 1 1      
         */
        ///////////

        xLuu = new int[nNgang * nDoc];
        yLuu = new int[nNgang * nDoc];
        for (int i = 0; i < nNgang * nDoc; i++) {
            xLuu[i] = -1;
            yLuu[i] = -1;
        }

        try {
            gameDesign = new GameDesign();

            Random rd = new Random();
            //
            int xAnh;
            int yAnh;

            anh = new Sprite[nDoc * nNgang][nCap * 2];

            for (int q = 0; q < (nDoc * nNgang) / (nCap * 2); q++) {
                for (int i = 0; i < nCap * 2; i++) {
                    do {
                        xAnh = rd.nextInt(nNgang);
                        yAnh = rd.nextInt(nDoc);
                    } while (ktTrung(xAnh, yAnh));

                    xLuu[q * nCap * 2 + i] = xAnh;
                    yLuu[q * nCap * 2 + i] = yAnh;
                    //
                    iGiongNhauX[xAnh][yAnh] = q;    // Vi tri cac' anh co' gia' tri. q
                    iGiongNhauY[xAnh][yAnh] = i;    // q[i]
                    //
                    anh[q][i] = new Sprite(Image.createImage("/pieces" + Integer.toString(q + 1) + ".png"));
                    anh[q][i].setPosition(40 + xAnh * 20, 50 + yAnh * 25);
                }
            }

            iBgLayer = gameDesign.getPlay_1();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        iLayerManager = new LayerManager();

        for (int q = 0; q < nNgang * nDoc / (nCap * 2); q++) {
            for (int i = 0; i < nCap * 2; i++) {
                iLayerManager.append(anh[q][i]);
            }
        }
        iLayerManager.append(iBgLayer);

        try {
            InputStream in1 = getClass().getResourceAsStream("/move.wav");
            moveSound = Manager.createPlayer(in1, "audio/x-wav");
            InputStream in2 = getClass().getResourceAsStream("/wrong.wav");
            wrongSound = Manager.createPlayer(in2, "audio/x-wav");
            InputStream in3 = getClass().getResourceAsStream("/Pause.wav");
            pauseSound = Manager.createPlayer(in3, "audio/x-wav");
            InputStream in4 = getClass().getResourceAsStream("/exit.wav");
            exitSound = Manager.createPlayer(in4, "audio/x-wav");
            InputStream in5 = getClass().getResourceAsStream("/gameover.wav");
            overSound = Manager.createPlayer(in5, "audio/x-wav");
            InputStream in6 = getClass().getResourceAsStream("/win.wav");
            winSound = Manager.createPlayer(in6, "audio/x-wav");
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (MediaException ex) {
            ex.printStackTrace();
        }


        iIsActive = true;
        Thread t = new Thread(this);
        t.start();
    }

    public void run() {
        while (iIsActive) {
            //processKeys(getKeyStates());
            if (!isPause || isWin) {
                updateWorld();
            }

            drawWorld();

            flushGraphics();
            try {
                Thread.sleep(delay);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }

    private void processKeys(int aKeyStates) {
        switch (aKeyStates) {
            case LEFT_PRESSED:
                if (x > 40) {
                    x = x - 20;
                } else {
                    x = 40 + (nNgang - 1) * 20;
                }
                break;

            case RIGHT_PRESSED:
                if (x < 40 + (nNgang - 1) * 20) {
                    x = x + 20;
                } else {
                    x = 40;
                }

                break;
            case UP_PRESSED:
                if (y > 50) {
                    y = y - 25;
                } else {
                    y = 50 + (nDoc - 1) * 25;
                }
                break;

            case DOWN_PRESSED:
                if (y < 50 + (nDoc - 1) * 25) {
                    y = y + 25;
                } else {
                    y = 50;
                }
                break;

            case FIRE_PRESSED: {
                int xx = (x - 40) / 20;
                int yy = (y - 50) / 25;
                // Kiem tra anh co' bi. xoa' hay chua <=> co' duong` di hay ko
                // neu' anh da~ bi xoa thi` ko cho chon
                if (maTranDuongDi[xx + 1][yy + 1] == 0) {
                    if (!daChon) {
                        xChon = x;
                        yChon = y;
                        daChon = true;
                    } else {
                        andiem = false;
                        int xxChon = (xChon - 40) / 20;
                        int yyChon = (yChon - 50) / 25;
                        // Neu chon cun`g 1 anh 2 lan` thi = voi' bo chon
                        if ((xChon == x) && (yChon == y)) {
                        } else {
                            if (ktGiongNhau(xxChon, yyChon, xx, yy)) {
                                path = new Point[(nNgang + 2) * (nDoc + 2)];
                                nPath = 0;
                                if (ktAnDiem(xxChon + 1, yyChon + 1, xx + 1, yy + 1, true)) {
                                    if (OptionScreen.getChon() == 1) {
                                        try {
                                            moveSound.start();
                                        } catch (MediaException ex) {
                                            ex.printStackTrace();
                                        }
                                    }
                                    andiem = true;
                                    iScore += 10;
                                    demve = 0;
                                    if (iGiongNhauX[xx][yy] == 18) {
                                        time = timeMax * 1000 / delay;
                                    }
                                    this.xxChon = xxChon;
                                    this.yyChon = yyChon;
                                    this.xx = xx;
                                    this.yy = yy;
                                    maTranDuongDi[xxChon + 1][yyChon + 1] = 1;
                                    maTranDuongDi[xx + 1][yy + 1] = 1;

                                    mtNoMove[xxChon][yyChon] = 0;
                                    mtNoMove[xx][yy] = 0;

                                } else {
                                    if (OptionScreen.getChon() == 1) {
                                        try {
                                            wrongSound.start();
                                        } catch (MediaException ex) {
                                            ex.printStackTrace();
                                        }
                                    }
                                }
                            } else {
                                if (OptionScreen.getChon() == 1) {
                                    try {
                                        wrongSound.start();
                                    } catch (MediaException ex) {
                                        ex.printStackTrace();
                                    }
                                }
                            }
                            daChon = false;
                        }
                    }
                }
                break;
            }
        }
    }
    int xxChon, yyChon, xx, yy;

    private void updateWorld() {
        processKeys(getKeyStates());
        if (demve != -1) {
            demve++;
        }

        if (demve == DelayVeDuongDi / delay) {
            int q1 = iGiongNhauX[xxChon][yyChon];
            int i1 = iGiongNhauY[xxChon][yyChon];
            setInvisible(q1, i1, anh);

            int q2 = iGiongNhauX[xx][yy];
            int i2 = iGiongNhauY[xx][yy];
            setInvisible(q2, i2, anh);
        }

        if (time > timeMax * 1000 / delay) {
            time = timeMax * 1000 / delay;
        }
        if (time > 0 && !isWin) {
            time--;
        }
        if (time < 0 && !isWin) {
            isOver = true;
            isPause = true;
            isExit = true;
            if (OptionScreen.getChon() == 1) {
                try {
                    overSound.start();
                } catch (MediaException ex) {
                    ex.printStackTrace();
                }
            }
        }

        if (ktWin() && time > 0) {
            isPause = true;
            isExit = true;
            isWin = true;
            if (OptionScreen.getChon() == 1) {
                try {
                    winSound.start();
                } catch (MediaException ex) {
                    ex.printStackTrace();
                }
            }
        }
        if (isWin) {
            if (time > 0) {
                if (time < 2 * 1000 / delay) {
                    iScore += 1;
                } else {
                    iScore += 2;
                }

                time -= 2 * 1000 / delay;
            } else {
                time = 0;
            }
        }

        if (isMove()) {
            //           isPause = true;
//            Random rd = new Random();
//            //
//            int xAnh;
//            int yAnh;
//            xLuu = new int[nNgang * nDoc];
//            yLuu = new int[nNgang * nDoc];
//
//            for (int q = 0; q < (nDoc * nNgang) / (nCap * 2); q++) {
//                for (int i = 0; i < nCap * 2; i++) {
//                    do {
//                        xAnh = rd.nextInt(nNgang);
//                        yAnh = rd.nextInt(nDoc);
//                    } while (ktTrung(xAnh, yAnh));
//
//                    xLuu[q * nCap * 2 + i] = xAnh;
//                    yLuu[q * nCap * 2 + i] = yAnh;
//                    //
//                    iGiongNhauX[xAnh][yAnh] = q;    // Vi tri cac' anh co' gia' tri. q
//                    iGiongNhauY[xAnh][yAnh] = i;    // q[i]
//
//                    if (anh[q][i].getX() != -100) {
//                        anh[q][i].setPosition(40 + xAnh * 20, 50 + yAnh * 25);
//                    }
//                }
//            }
        }
    }

    public boolean ktWin() {
        for (int i = 0; i < nNgang + 2; ++i) {
            for (int j = 0; j < nDoc + 2; ++j) {
                if (maTranDuongDi[i][j] == 0) {
                    return false;
                }
            }
        }
        return true;
    }

    public boolean ktTrung(int x, int y) {
        boolean kt = false;
        for (int i = 0; i < nNgang * nDoc; i++) {
            if (x == xLuu[i] && y == yLuu[i]) {
                kt = true;
            }
        }
        return kt;
    }
    ////////////////////////////

    public boolean ktGiongNhau(int x1, int y1, int x2, int y2) {
        if (iGiongNhauX[x1][y1] == iGiongNhauX[x2][y2]) {
            return true;
        }
        return false;
    }

    public void setInvisible(int x, int y, Sprite s[][]) {
        s[x][y].setVisible(false);
        s[x][y].setPosition(-100, -100);
    }

    /*
    Type of line
     * |  
     * |  ---  --|   |      |    |--
     * |         |   |--  --|    |
     * 1   2     3   4     5     6
     */
    public int typeOfLine(Point p1, Point p2, Point p3) {
        if (p1.getX() == p2.getX()
                && p2.getX() == p3.getX()) {
            return 1;
        }
        if (p1.getY() == p2.getY()
                && p2.getY() == p3.getY()) {
            return 2;
        }

        if (((p1.getX() - 1) == p3.getX()) && ((p1.getY() - 1) == p3.getY())
                || ((p3.getX() - 1) == p1.getX()) && ((p3.getY() - 1) == p1.getY())) {
            if ((p1.getX() < p2.getX())
                    || (p3.getX() < p2.getX())) {
                return 3;
            } else {
                return 4;
            }
        } else {
            if (p1.getY() < p2.getY()
                    || p3.getY() < p2.getY()) {
                return 5;
            } else {
                return 6;
            }
        }
        // return 0;
    }

    public boolean TheoHangNgang(int sx, int sy, int ex, int ey, boolean getPath) {
        if (sy == ey) {
            if (sx < ex) {
                for (int i = sx + 1; i < ex; i++) {
                    if (maTranDuongDi[i][sy] == 0) {
                        return false;
                    }
                }
            } else {
                for (int i = sx - 1; i > ex; i--) {
                    if (maTranDuongDi[i][sy] == 0) {
                        return false;
                    }
                }
            }
            if (getPath) {
                if (nPath == 0) {
                    path[nPath++] = new Point(sx, sy);
                }
                if (sx < ex) {
                    for (int j = sx + 1; j < ex; j++) {
                        path[nPath++] = new Point(j, sy);
                    }
                } else {
                    for (int j = sx - 1; j > ex; j--) {
                        path[nPath++] = new Point(j, sy);
                    }
                }
                path[nPath++] = new Point(ex, ey);
            }
            return true;
        }
        return false;
    }

    public boolean TheoHangDoc(int sx, int sy, int ex, int ey, boolean getPath) {
        if (sx == ex) {
            if (sy < ey) {
                for (int i = sy + 1; i < ey; i++) {
                    if (maTranDuongDi[sx][i] == 0) {
                        return false;
                    }
                }
            } else {
                for (int i = sy - 1; i > ey; i--) {
                    if (maTranDuongDi[sx][i] == 0) {
                        return false;
                    }
                }
            }
            if (getPath) {
                if (nPath == 0) {
                    path[nPath++] = new Point(sx, sy);
                }
                if (sy < ey) {
                    for (int j = sy + 1; j < ey; j++) {
                        path[nPath++] = new Point(sx, j);
                    }
                } else {
                    for (int j = sy - 1; j > ey; j--) {
                        path[nPath++] = new Point(sx, j);
                    }
                }
                path[nPath++] = new Point(ex, ey);
            }
            return true;
        }
        return false;
    }
    /*
    |           |   |----   ----   
    |           |   |          |
    |----   ----|   |          |
     */

    public boolean Theo2Duong(int sx, int sy, int ex, int ey, boolean getPath) {

        boolean st;
        Point top, bot;
        Point mid_top, mid_bot;
        if (sy < ey) {   // pStart na`m tren, pEnd nam` duoi'
            st = true;
            top = new Point(sx, sy);
            bot = new Point(ex, ey);
            mid_top = new Point(ex, sy);
            mid_bot = new Point(sx, ey);
        } else {
            st = false;
            top = new Point(ex, ey);
            bot = new Point(sx, sy);
            mid_top = new Point(sx, ey);
            mid_bot = new Point(ex, sy);
        }

        if (top.getX() < bot.getX()) {
            if (maTranDuongDi[mid_top.getX()][mid_top.getY()] != 0) {
                if (TheoHangNgang(top.getX(), top.getY(), mid_top.getX(), mid_top.getY(), false)) {
                    if (TheoHangDoc(mid_top.getX(), mid_top.getY(), bot.getX(), bot.getY(), false)) {
                        if (getPath) {
                            if (st) {
                                TheoHangNgang(top.getX(), top.getY(), mid_top.getX(), mid_top.getY(), true);
                                TheoHangDoc(mid_top.getX(), mid_top.getY(), bot.getX(), bot.getY(), true);
                            } else {
                                TheoHangDoc(bot.getX(), bot.getY(), mid_top.getX(), mid_top.getY(), true);
                                TheoHangNgang(mid_top.getX(), mid_top.getY(), top.getX(), top.getY(), true);
                            }
                        }
                        return true;
                    }
                }
            }
            if (maTranDuongDi[mid_bot.getX()][mid_bot.getY()] != 0) {
                if (TheoHangDoc(top.getX(), top.getY(), mid_bot.getX(), mid_bot.getY(), false)) {
                    if (TheoHangNgang(mid_bot.getX(), mid_bot.getY(), bot.getX(), bot.getY(), false)) {
                        if (getPath) {
                            if (st) {
                                TheoHangDoc(top.getX(), top.getY(), mid_bot.getX(), mid_bot.getY(), true);
                                TheoHangNgang(mid_bot.getX(), mid_bot.getY(), bot.getX(), bot.getY(), true);
                            } else {
                                TheoHangNgang(bot.getX(), bot.getY(), mid_bot.getX(), mid_bot.getY(), true);
                                TheoHangDoc(mid_bot.getX(), mid_bot.getY(), top.getX(), top.getY(), true);
                            }
                        }
                        return true;
                    }
                }
            }
        } else {
            if (maTranDuongDi[mid_top.getX()][mid_top.getY()] != 0) {
                if (TheoHangNgang(mid_top.getX(), mid_top.getY(), top.getX(), top.getY(), false)) {
                    if (TheoHangDoc(mid_top.getX(), mid_top.getY(), bot.getX(), bot.getY(), false)) {
                        if (getPath) {
                            if (st) {
                                TheoHangNgang(top.getX(), top.getY(), mid_top.getX(), mid_top.getY(), true);
                                TheoHangDoc(mid_top.getX(), mid_top.getY(), bot.getX(), bot.getY(), true);
                            } else {
                                TheoHangDoc(bot.getX(), bot.getY(), mid_top.getX(), mid_top.getY(), true);
                                TheoHangNgang(mid_top.getX(), mid_top.getY(), top.getX(), top.getY(), true);
                            }
                        }
                        return true;
                    }
                }
            }
            if (maTranDuongDi[mid_bot.getX()][mid_bot.getY()] != 0) {
                if (TheoHangDoc(top.getX(), top.getY(), mid_bot.getX(), mid_bot.getY(), false)) {
                    if (TheoHangNgang(bot.getX(), bot.getY(), mid_bot.getX(), mid_bot.getY(), false)) {
                        if (getPath) {
                            if (st) {
                                TheoHangDoc(top.getX(), top.getY(), mid_bot.getX(), mid_bot.getY(), true);
                                TheoHangNgang(mid_bot.getX(), mid_bot.getY(), bot.getX(), bot.getY(), true);
                            } else {
                                TheoHangNgang(bot.getX(), bot.getY(), mid_bot.getX(), mid_bot.getY(), true);
                                TheoHangDoc(mid_bot.getX(), mid_bot.getY(), top.getX(), top.getY(), true);
                            }
                        }
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public boolean Theo3Duong(int sx, int sy, int ex, int ey, boolean draw) {
        for (int tren = sy - 1; tren >= 0; tren--) {
            if (maTranDuongDi[sx][tren] != 0) {
                if (TheoHangDoc(sx, sy, sx, tren, false) && Theo2Duong(sx, tren, ex, ey, false)) {
                    if (draw) {
                        TheoHangDoc(sx, sy, sx, tren, true);
                        Theo2Duong(sx, tren, ex, ey, true);
                    }
                    return true;
                }
            } else {
                break;
            }
        }

        for (int duoi = sy + 1; duoi < nDoc + 2; duoi++) {
            if (maTranDuongDi[sx][duoi] != 0) {
                if (TheoHangDoc(sx, sy, sx, duoi, false) && Theo2Duong(sx, duoi, ex, ey, false)) {
                    if (draw) {
                        TheoHangDoc(sx, sy, sx, duoi, true);
                        Theo2Duong(sx, duoi, ex, ey, true);
                    }
                    return true;
                }
            } else {
                break;
            }
        }

        for (int trai = sx - 1; trai >= 0; trai--) {
            if (maTranDuongDi[trai][sy] != 0) {
                if (TheoHangNgang(sx, sy, trai, sy, false) && Theo2Duong(trai, sy, ex, ey, false)) {
                    if (draw) {
                        TheoHangNgang(sx, sy, trai, sy, true);
                        Theo2Duong(trai, sy, ex, ey, true);
                    }
                    return true;
                }
            } else {
                break;
            }
        }

        for (int phai = sx + 1; phai < nNgang + 2; phai++) {
            if (maTranDuongDi[phai][sy] != 0) {
                if (TheoHangNgang(sx, sy, phai, sy, false) && Theo2Duong(phai, sy, ex, ey, false)) {
                    if (draw) {
                        TheoHangNgang(sx, sy, phai, sy, true);
                        Theo2Duong(phai, sy, ex, ey, true);
                    }
                    return true;
                }
            } else {
                break;
            }
        }
        return false;
    }

    public boolean ktAnDiem(int sx, int sy, int ex, int ey, boolean draw) {
        if (TheoHangNgang(sx, sy, ex, ey, false)) {
            if (draw) {
                TheoHangNgang(sx, sy, ex, ey, true);
                andiem = true;
            }

            return true;
        }
        if (TheoHangDoc(sx, sy, ex, ey, false)) {
            if (draw) {
                TheoHangDoc(sx, sy, ex, ey, true);
                andiem = true;
            }

            return true;
        }
        if (Theo2Duong(sx, sy, ex, ey, false)) {
            if (draw) {
                Theo2Duong(sx, sy, ex, ey, true);
                andiem = true;
            }

            return true;
        }
        if (Theo3Duong(sx, sy, ex, ey, false)) {
            if (draw) {
                Theo3Duong(sx, sy, ex, ey, true);
                andiem = true;
            }

            return true;
        }
        return false;
    }

    private boolean isMove() {
        for (int i = 0; i < nNgang; i++) {
            for (int j = 0; j < nDoc; j++) {
                for (int h = 0; h < nNgang; h++) {
                    for (int k = 0; k < nDoc; k++) {
                        if (mtNoMove[h][k] == 1) {
                            if (mtNoMove[i][j] == 1) {
                                if (i != h && j != k) {
                                    if (ktAnDiem(i + 1, j + 1, h + 1, k + 1, false)) {
                                        return true;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return false;
    }

    public void drawPath(Point p[], int np, Graphics gr) {
        gr.setColor(255, 165, 0);
        int dx, dy, dx2, dy2;
        dx = (20 + (p[0].getX()) * 20) + 10;
        dy = 25 + (p[0].getY()) * 25 + 25 / 2;
        dx2 = (20 + (p[1].getX()) * 20) + 10;
        dy2 = 25 + (p[1].getY()) * 25 + 25 / 2;

        if (p[0].getX() == p[1].getX()) {
            if (dy < dy2) {
                gr.fillRect(dx - 1, dy, 3, Math.abs(dy - dy2));
            } else {
                gr.fillRect(dx2 - 1, dy2, 3, Math.abs(dy - dy2));
            }
        }
        if (p[0].getY() == p[1].getY()) {
            if (dx < dx2) {
                gr.fillRect(dx, dy - 1, Math.abs(dx - dx2), 3);
            } else {
                gr.fillRect(dx2, dy2 - 1, Math.abs(dx - dx2), 3);
            }
        }
        if (np >= 3) {
            for (int i = 1; i < np - 1; i++) {
                switch (typeOfLine(p[i - 1], p[i], p[i + 1])) {
                    case 1: {
                        dx = (20 + (p[i].getX()) * 20) + 10;
                        dy = 25 + (p[i].getY()) * 25;
                        gr.drawLine(dx, dy, dx, dy + 25);
                        gr.drawLine(dx - 1, dy, dx - 1, dy + 25);
                        gr.drawLine(dx + 1, dy, dx + 1, dy + 25);
                    }
                    break;
                    case 2: {
                        dx = (20 + (p[i].getX()) * 20);
                        dy = 25 + (p[i].getY()) * 25 + 25 / 2;
                        gr.drawLine(dx, dy, dx + 20, dy);
                        gr.drawLine(dx, dy - 1, dx + 20, dy - 1);
                        gr.drawLine(dx, dy + 1, dx + 20, dy + 1);
                    }
                    break;
                    case 3: {
                        dx = (20 + (p[i].getX()) * 20);
                        dy = 25 + (p[i].getY()) * 25 + 25 / 2;
                        gr.drawLine(dx, dy, dx + 10, dy);
                        gr.drawLine(dx, dy - 1, dx + 10, dy - 1);
                        gr.drawLine(dx, dy + 1, dx + 10, dy + 1);

                        gr.drawLine(dx + 10, dy, dx + 10, dy + 25 / 2 + 1);
                        gr.drawLine(dx + 9, dy, dx + 9, dy + 25 / 2 + 1);
                        gr.drawLine(dx + 11, dy, dx + 11, dy + 25 / 2 + 1);
                    }
                    break;
                    case 4: {
                        dx = (20 + (p[i].getX()) * 20) + 10;
                        dy = 25 + (p[i].getY()) * 25;
                        gr.drawLine(dx, dy, dx, dy + 25 / 2);
                        gr.drawLine(dx - 1, dy, dx - 1, dy + 25 / 2);
                        gr.drawLine(dx + 1, dy, dx + 1, dy + 25 / 2);

                        gr.drawLine(dx, dy + 25 / 2, dx + 10, dy + 25 / 2);
                        gr.drawLine(dx, dy + 25 / 2 - 1, dx + 10, dy + 25 / 2 - 1);
                        gr.drawLine(dx, dy + 25 / 2 + 1, dx + 10, dy + 25 / 2 + 1);
                    }
                    break;
                    case 5: {
                        dx = (20 + (p[i].getX()) * 20) + 10;
                        dy = 25 + (p[i].getY()) * 25 + 25 / 2;
                        gr.drawLine(dx, dy - 25 / 2, dx, dy);
                        gr.drawLine(dx - 1, dy - 25 / 2, dx - 1, dy);
                        gr.drawLine(dx + 1, dy - 25 / 2, dx + 1, dy);

                        gr.drawLine(dx, dy, dx - 10, dy);
                        gr.drawLine(dx, dy - 1, dx - 10, dy - 1);
                        gr.drawLine(dx, dy + 1, dx - 10, dy + 1);
                    }
                    break;
                    case 6: {
                        dx = (20 + (p[i].getX()) * 20) + 10;
                        dy = 25 + (p[i].getY()) * 25 + 25 / 2;

                        gr.drawLine(dx, dy + 25 / 2 + 1, dx, dy);
                        gr.drawLine(dx - 1, dy + 25 / 2 + 1, dx - 1, dy);
                        gr.drawLine(dx + 1, dy + 25 / 2 + 1, dx + 1, dy);

                        gr.drawLine(dx, dy, dx + 10, dy);
                        gr.drawLine(dx, dy - 1, dx + 10, dy - 1);
                        gr.drawLine(dx, dy + 1, dx + 10, dy + 1);
                    }
                    break;
                }
            }
        }

        dx = (20 + (p[np - 2].getX()) * 20) + 10;
        dy = 25 + (p[np - 2].getY()) * 25 + 25 / 2;
        dx2 = (20 + (p[np - 1].getX()) * 20) + 10;
        dy2 = 25 + (p[np - 1].getY()) * 25 + 25 / 2;

        if (p[np - 2].getX() == p[np - 1].getX()) {
            if (dy < dy2) {
                gr.fillRect(dx - 1, dy, 3, Math.abs(dy - dy2));
            } else {
                gr.fillRect(dx2 - 1, dy2, 3, Math.abs(dy - dy2));
            }
        }
        if (p[np - 2].getY() == p[np - 1].getY()) {
            if (dx < dx2) {
                gr.fillRect(dx, dy - 1, Math.abs(dx - dx2), 3);
            } else {
                gr.fillRect(dx2, dy2 - 1, Math.abs(dx - dx2), 3);
            }
        }
    }

//////////////
    private void drawWorld() {
        if (!isPause || isWin) {
            iLayerManager.paint(g, 0, 0);

            // To khung thoi gian
            g.setColor(0, 0, 0);
            g.drawRect(19, 24, 202, 9);
            g.drawRect(18, 23, 204, 11);

            // Cho thanh thoi gian ngan dan
            Random rd = new Random();
            int timemax = timeMax * 1000 / delay;
            if (time >= timemax - 20 * 1000 / delay) {
                g.setColor(30, 144, 255);
            } else if (time <= 20 * 1000 / delay) {
                g.setColor(rd.nextInt(0xffffff));
            } else if (time >= timemax - 40 * 1000 / delay) {
                g.setColor(141, 182, 205);
            } else if (time >= timemax - 60 * 1000 / delay) {
                g.setColor(255, 185, 15);
            } else if (time >= timemax - 80 * 1000 / delay) {
                g.setColor(255, 106, 106);
            } else if (time >= timemax - 100 * 1000 / delay) {
                g.setColor(255, 105, 180);
            } else if (time >= timemax - 120 * 1000 / delay) {
                g.setColor(255, 0, 0);
            } else {
                g.setColor(147, 112, 219);
            }
            int conLai = (int) (time * 200 / timemax);
            g.fillRect(20, 25, conLai, 8);

            g.setColor(139, 0, 0);
            g.drawRect(x, y, 20, 25);
            g.drawRect(x + 1, y + 1, 18, 23);

            if (daChon) {
                g.setColor(rd.nextInt(0xffffff));
                g.drawRect(xChon, yChon, 20, 25);
                g.drawRect(xChon + 1, yChon + 1, 20 - 2, 25 - 2);
            }

            if (andiem && (demve < DelayVeDuongDi / delay)) {
                drawPath(path, nPath, g);
            }
            g.setColor(248, 248, 255);
            g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
            g.drawString("Score: " + iScore, 10, 5, Graphics.TOP | Graphics.LEFT);

            g.setColor(248, 248, 255);
            g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
            g.drawString("Time: " + time * delay / 1000, 230, 5, Graphics.TOP | Graphics.RIGHT);
        }
        if (isPause && !isWin) {
            if (!isOver) {
                g.drawImage(imgPause, 0, 50, Graphics.TOP | Graphics.LEFT);
            } else {
                g.drawImage(imgOver, 120, 150, Graphics.VCENTER | Graphics.HCENTER);
            }
        }
        if (isExit && flag && !isWin) {
            if (!isOver) {
                g.drawImage(imgQuit, 0, 50, Graphics.TOP | Graphics.LEFT);
            }
        }
        Random rd = new Random();
        if (isWin) {
            g.drawImage(imgWin, 0, 43, Graphics.TOP | Graphics.LEFT);
        }
        flushGraphics();
    }

    public void stop() {
        iIsActive = false;
    }
    int dem = 0;

    public void pause() {
        dem++;
        if (dem % 2 != 0) {
            isExit = true;
            isPause = true;
        } else {
            isPause = false;
            isExit = false;
        }
    }

    public void exit() {
        int kt = iMain.ktDuocLuu(Integer.toString(iScore));
        if (kt == 1) {
            iAddScore = new AddScore(iMain, Integer.toString(iScore), iMenuScreen);
            Display.getDisplay(iMain).setCurrent(iAddScore);
        } else if (kt == 2) {

            iAddScore = new AddScore(iMain, Integer.toString(iScore), iMenuScreen);
            Display.getDisplay(iMain).setCurrent(iAddScore);
        } else {
            Display.getDisplay(iMain).setCurrent(iMenuScreen);
        }

        stop();
    }
    boolean flag = false;

    public void commandAction(Command command, Displayable displayable) {
        if (command == cmdExit) {
            if (!isExit) {
                try {
                    pauseSound.start();
                } catch (MediaException ex) {
                    ex.printStackTrace();
                }
                flag = true;
                isExit = true;
                isPause = true;
            } else {
                try {
                    exitSound.start();
                } catch (MediaException ex) {
                    ex.printStackTrace();
                }
                exit();
            }
        }

        if (command == cmdPause) {
            if (isOver || isWin) {
                return;
            }
            try {
                pauseSound.start();
            } catch (MediaException ex) {
                ex.printStackTrace();
            }
            pause();
            if (flag == true) {
                flag = false;
                isExit = false;
                isPause = false;
                if (dem % 2 != 0) {
                    dem++;
                }
            }
        }
    }
}
